<?php  
  
/** 
 * Swoole服务器 
 */
class Swoole_SwooleServer
{
    private $logger = null;
    private $server = null;
    private $smtpConfig;
    private $app;
    private $options = array();

    public function __construct($ip,$port)
    {
        $this->server = new swoole_server($ip, $port);
        $this->server->set([
            'worker_num' => 8, //工作进程
            'reactor_num' => 8, //reactor线程数
            'daemonize' => false, //守护进程化。设置daemonize => 1时，程序将转入后台作为守护进程运行。长时间运行的服务器端程序必须启用此项
            'max_request' => 10000,//设置worker进程的最大任务数。一个worker进程在处理完超过此数值的任务后将自动退出。这个参数是为了防止PHP进程内存溢出。 
            'dispatch_mode' => 2,//数据包分发策略。可以选择3种类型，默认为2 
            'debug_mode'=> 1,//调试模式是否开启
            'log_file' =>  "/var/log/swoole_{$port}.log",//日志存放路径
            'pid_file' => __DIR__.'/server.pid',//进程ID
        ]);

        $this->server->on('Start', [$this, 'onStart']);
        //处理异步任务
        $this->server->on('task', [$this, 'onTask']);
        //处理异步任务的结果
        $this->server->on('finish', [$this, 'onFinish']);
        $this->server->on('WorkerStart' , [$this , 'onWorkerStart']);
        $this->server->on('Connect', [$this, 'onConnect']);
        $this->server->on('Receive', [$this, 'onReceive']);
        $this->server->on('Close', [$this, 'onClose']);
        $this->server->start();
    }

    public function onStart()
    {

    }

    public function onConnect($server, $descriptors, $fromId)
    {

    }

    public function onReceive(swoole_server $server, $descriptors, $fromId, $data)
    {
        //调用shell
        $sent = $this->doit($data);// Swoole Server 接受到任务后调用发送动作

    }
    public function onTask(swoole_server $server, $task_id, $from_id, $data)
    {
        echo "New AsyncTask[id=$task_id]".PHP_EOL;
        $this->dotask($data);

        //返回任务执行的结果
        $server->finish("$data -> OK");
    }
    public function onFinish(swoole_server $server, $task_id, $data)
    {
        echo "AsyncTask[$task_id] Finish: $data".PHP_EOL;

    }

    public function onClose($server, $descriptors, $fromId)
    {

    }

    public function onWorkerStart() {
        //worker开始工作前预定义变量
        $this->app = new Yaf_Application(APP_PATH . '/app.ini', 'development');
    }
    public function doit($data)
    {
        //执行代码
        $opt = json_decode($data, true);
        //开启缓冲区
        if(isset($string)) unset($string);
        try{
            ob_start();
            //$resonpse = $this->app->bootstrap()->getDispatcher()->returnResponse(false)->dispatch($request);
            $shell_str = "php cli.php -c '{$opt['c']}' -a '{$opt['a']}' -p '{$opt['p']}'";
            passthru($shell_str);
            $string = ob_get_contents();
            ob_end_clean();
            Log::record('[REQUEST]' . $data . '[RUNSHELL] '.$shell_str. ' [RESPONSE] ' . $string ,'swoole_data',true);

        } catch (\Exception $exception) {
           //记录错误日志
        }
        unset($opt,$data,$string,$shell_str,$result_msg,$exceptionText);
    }
    public function dotask($data)
    {
        $opt = json_decode($data, true);

        //Log::record('[REQUEST]' . $data,'swoole_data',true);
        if(isset($request)) $result = null;
        $request = new Yaf_Request_Simple();;// Yaf 命令行
        $request->setRequestUri($opt['c'] . "/" . $opt['a']);
        //参数
        if(isset($opt['p']) && $opt['p']){
            parse_str($opt['p'], $params);
            if(is_array($params)){
                foreach ($params as $key=>$value){
                    $request->setParam($key,$value);
                }
            }
        }

        //开启缓冲区
        if(isset($string)) unset($string);
        try{
            ob_start();
            $resonpse = $this->app->bootstrap()->getDispatcher()->returnResponse(false)->dispatch($request);
            $string = ob_get_contents();
            ob_end_clean();
            Log::record('[REQUEST]' . $data . ' [RESPONSE] ' . $string ,'swoole_data',true);
        } catch (\Exception $exception) {
             //记录错误日志
        }
        unset($opt,$data,$string,$result_msg,$exceptionText);

        //Yaf_Dispatcher::getInstance()->autoRender(false);

    }

}

set_time_limit(0); // 设置超时时间为0
//读取配置
$arr_ini = parse_ini_file(__DIR__. '/app.ini');
$ip = $arr_ini['swoole.ip'];
$port = $arr_ini['swoole.port'];
if($ip && $port) {
    $server = new Swoole_SwooleServer($ip,$port);
}else{
    echo "\033[31m 获取IP或Port为空!\033[0m";
}